package com.lazyframework.commons.util;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.net.URL;

/**
 * 图片加水印
 *
 * Create by lazy in 2020.07.18
 */
public class ImageWatermarkUtils {

    /**
     * 水印位置-左上角（x、y轴各留50间距）
     */
    public static final int POSITION_LEFT_TOP = 1;

    /**
     * 水印位置-左下角（x、y轴各留50间距）
     */
    public static final int POSITION_LEFT_BOTTOM = 2;

    /**
     * 水印位置-右上角（x、y轴各留50间距）
     */
    public static final int POSITION_RIGHT_TOP = 3;

    /**
     * 水印位置-右下角（x、y轴各留50间距）
     */
    public static final int POSITION_RIGHT_BOTTOM = 4;

    /**
     * 水印位置-铺满整张图（x、y轴各留80间距）
     */
    public static final int POSITION_FILL = 5;

    /**
     * 默认添加了水印后的图片保存格式
     */
    private static final String IMG_FMT = "JPG";

    /**
     * 水印透明度
     */
    private static final float WATERMARK_ALPHA = 0.6f;

    /**
     * 水印X轴间隔
     */
    private static final int WATERMARK_MARGIN_X = 80;

    /**
     * 水印Y轴间隔
     */
    private static final int WATERMARK_MARGIN_Y = 80;


    /**
     * 添加水印
     *
     * @param file 本地图片文件
     * @param text 水印文件
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(File file, String text) throws IOException {
        return addWatermark(file, text, POSITION_FILL);
    }

    /**
     * 添加水印
     *
     * @param file     本地图片文件
     * @param text     水印文字
     * @param position 水印位置
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(File file, String text, int position) throws IOException {
        return addWatermark(file, text, position, IMG_FMT);
    }

    /**
     * 添加水印
     *
     * @param file   本地图片文件
     * @param text   水印文件
     * @param format 图片保存格式
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(File file, String text, int position, String format) throws IOException {
        return addWatermark(ImageIO.read(file), text, position, format);
    }

    /**
     * 添加水印
     *
     * @param url  网络图片路径
     * @param text 水印文件
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(URL url, String text) throws IOException {
        return addWatermark(url, text, POSITION_FILL);
    }

    /**
     * 添加水印
     *
     * @param url      网络图片路径
     * @param text     水印文件
     * @param position 水印位置
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(URL url, String text, int position) throws IOException {
        return addWatermark(url, text, position, IMG_FMT);
    }

    /**
     * 添加水印
     *
     * @param url      网络图片路径
     * @param text     水印文字
     * @param position 水印位置
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(URL url, String text, int position, String format) throws IOException {
        return addWatermark(ImageIO.read(url), text, position, format);
    }

    /**
     * 添加水印
     *
     * @param bufferedImage 原图
     * @param text          水印文字
     * @param position      水印位置
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(BufferedImage bufferedImage, String text, int position) throws IOException {
        return addWatermark(bufferedImage, text, position, IMG_FMT);
    }

    /**
     * 添加水印
     *
     * @param bufferedImage 原图
     * @param text          水印文字
     * @param format        图片保存格式
     * @param position      水印位置
     * @return
     * @throws IOException
     */
    public static byte[] addWatermark(BufferedImage bufferedImage, String text, int position, String format) throws IOException {
        // 原图宽高
        int width = bufferedImage.getWidth(), height = bufferedImage.getHeight();

        // 创建画布
        BufferedImage newImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics2D = newImage.createGraphics();

        // 底图
        graphics2D.drawImage(bufferedImage, 0, 0, width, height, null);

        // 文字水印
        graphics2D.setColor(Color.WHITE);
        graphics2D.setFont(new Font("微软雅黑", Font.BOLD, 36));                              // 字体
        graphics2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP, WATERMARK_ALPHA));  // 水印透明度

        int markHeight = 36;                        // 字体高度
        int markWidth = 36 * getTxtLength(text);    // 字体长度

        // 铺满整张图
        if (position == 5) {
            // 旋转
            graphics2D.rotate(Math.toRadians(-40), (double) width / 2, (double) height / 2);
            // 循环添加
            int x = -width / 2, y;
            while (x < width * 1.5) {
                y = -height / 2;
                while (y < height * 1.5) {
                    graphics2D.drawString(text, x, y);
                    y += markHeight + WATERMARK_MARGIN_Y;
                }
                x += markWidth + WATERMARK_MARGIN_X;
            }
        } else {
            int x, y, offset_x, offset_y;
            offset_x = offset_y = 50;
            switch (position) {
                case 1: {
                    x = offset_x;
                    y = offset_y + markHeight;
                    break;
                }
                case 2: {
                    x = offset_x;
                    y = height - offset_y;
                    break;
                }
                case 3: {
                    x = width - markWidth - offset_x;
                    y = offset_y + markHeight;
                    break;
                }
                case 4: {
                    x = width - markWidth - offset_x;
                    y = height - offset_y;
                    break;
                }
                default: {
                    x = width - markWidth - offset_x;
                    y = height - offset_y;
                }
            }
            graphics2D.drawString(text, x, y);
        }

        // 释放资源
        graphics2D.dispose();

        // 以字节数组形式返回
        try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
            ImageIO.write(newImage, format, bos);
            return bos.toByteArray();
        }
    }

    /**
     * 获取文本长度。汉字为1:1，英文和数字为2:1
     *
     * @param text
     * @return
     */
    private static int getTxtLength(String text) {
        int length = text.length();
        for (int i = 0; i < text.length(); i++) {
            String s = String.valueOf(text.charAt(i));
            if (s.getBytes().length > 1) {
                length++;
            }
        }
        length = length % 2 == 0 ? length / 2 : length / 2 + 1;
        return length;
    }

}
